/**
 * Copyright (c) 2009  Collaborative Development Group, C.S. Dept., University of Bari
 *
 * All rights reserved. This program and the accompanying materials are made available under
 * the terms of the Eclipse Public License v1.0  which accompanies this distribution, and is 
 * available at http://www.eclipse.org/legal/epl-v10.html
 */
package it.uniba.di.cdg.penelope;

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;

/**
 * This aspect provides the basic interception of a Plugin Lifecycle: each plugin should derive its own aspect
 * reimplementing {@link AbstractBundleLifecycleAwareAspect#thisBundleActivator()}. For example:
 * <code><pre>
 * @Aspect( "perthis( thisBundleActivator() )" ) // @Aspect annotations is not inherited :(
 * public class MyPluginLifeCycle extends AbstractBundleLifecycleAwareAspect {
 *    @Pointcut( "this( my.plugin.internal.Activator )" )
 *    protected void thisBundleActivator() {}
 *    
 *    @Override
 *    protected void onBundleActivated( BundleContext bc ) {
 *       System.out.println( "Plung-in has been activated!" );
 *    }
 * }
 * </pre></code>
 * In the example we define a concrete aspect which is to be wired only to the actual Activator instance and
 * re-implement the lifecycle method {@link AbstractBundleLifecycleAwareAspect#onBundleActivated(BundleContext)}
 * to perform some custom action.
 */
@Aspect
public abstract class AbstractBundleLifecycleAwareAspect {
	/**
	 * The bundle context associated to this bundle aspect.
	 */
	private BundleContext bundleContext;

	@Pointcut( "" )
	protected abstract void thisBundleActivator();
	
	@Pointcut( "thisBundleActivator() && execution( public void org.osgi.framework.BundleActivator+.start( org.osgi.framework.BundleContext ) ) && args( bc )" )
	protected void bundleActivation( BundleContext bc ) { }
	
	@Pointcut( "thisBundleActivator() && execution( public void org.osgi.framework.BundleActivator+.stop( org.osgi.framework.BundleContext ) ) && args( bc )" )
	protected void bundleDeactivation( BundleContext bc ) { }


	@After( "bundleActivation( bc )" )
	public final void afterActivation( BundleContext bc ) {
		this.bundleContext = bc;
		onBundleActivated( bc );
	}
	
	@Before( "bundleDeactivation( bc )" )
	public final void beforeDeactivation( BundleContext bc ) {
		onBundleDeactivating( bc );
		this.bundleContext = null;
	}

	/**
	 * Called after the {@linkplain BundleActivator#start(BundleContext)} method has been executed.
	 * @param bc 
	 */
	protected void onBundleActivated( BundleContext bc ) {
		// Nothing
	}

	/**
	 * Called before the {@linkplain BundleActivator#stop(BundleContext)} is called (that is, before bundle
	 * deactivation).
	 * @param bc 
	 */
	protected void onBundleDeactivating( BundleContext bc ) {
		// Nothing
	}
	
	/**
	 * Returns the bundle context associated to the bundle this aspect has been woven to.
	 * @return the captured bundle context.
	 */
	protected BundleContext getBundleContext() {
		return bundleContext;
	}	
}
